package org.jpropelleralt.jview;

import javax.swing.Box;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JTextField;

import org.jpropelleralt.view.View;
import org.jpropelleralt.view.update.UpdatableView;

/**
 * An {@link UpdatableView} which has a UI component ( {@link JComponent} )
 * to be displayed in a GUI
 */
public interface JView extends UpdatableView {

	/**
	 * This describes the format of the JView, for
	 * example it may be a small single line component,
	 * a medium sized component that spans several "lines",
	 * or a large component that users may wish to hide
	 */
	public enum Format {
		/**
		 * Component is essentially a single line - for example
		 * a text field, a checkbox, etc.
		 */
		SINGLE_LINE,
		
		/**
		 * Component is not a single line, but is still suitable
		 * for direct display grouped with other editors, for
		 * example in a list, etc.
		 */
		MEDIUM,
		
		/**
		 * Component is large - it is probably essentially an
		 * entire panel, and so should be displayed separately,
		 * or with provision for hiding the component if it
		 * is grouped with other editors, for example in a list
		 */
		LARGE
	}
	
	/**
	 * Get the {@link JComponent} that displays the view.
	 * 
	 * Implementors of {@link JView} should be very careful to consider the
	 * following situation when creating their {@link JComponent}:
	 * 
	 * {@link JView}s aren't kept alive by the data they are listening to, 
	 * and generally aren't very interesting to their users - 
	 * when making a UI it is common to just make some {@link JView}s, 
	 * put their JComponents into the UI, then forget about the JViews. 
	 * This means the {@link JView}s are likely to be GCed, leaving 
	 * the orphan {@link JComponent}s without updates and other logic.
	 * 
	 * To avoid this, {@link JView} implementations  should make sure 
	 * that the {@link JComponent} available from {@link #getComponent()}
	 * also has a link back to the {@link JView} itself. This will cause 
	 * the {@link JView} to remain in scope as long as its {@link JComponent} 
	 * does. Of course once the {@link JComponent} is no longer in scope, 
	 * the {@link JView} will be GCed as required (unless there is a 
	 * separate strong link to it - the Box->View link is weak and so 
	 * allows the JView to be GCed). This is very useful since we 
	 * don't need to worry about having a "dispose()" method, or 
	 * removing {@link View}s from {@link Box}es, the garbage collector 
	 * will get rid of things as necessary, for us.
	 * 
	 * The recommended approach is to just create a trivial subclass of
	 * the {@link JComponent} class returned here, and give it a private
	 * field referencing the {@link JView} that makes it. Only the top-level
	 * {@link JComponent} needs to have this link, so that it will keep
	 * the {@link JView} alive while it is used.
	 * 
	 * @return
	 * 		The view {@link JComponent}
	 */
	public JComponent getComponent();
	
	/**
	 * True if the view contains its own name - false if the name should be displayed
	 * alongside it (as appropriate)
	 * For example, this is true for {@link JCheckBox}-type controls that contain the
	 * name of the edited model as part of the view, and false for controls like
	 * {@link JTextField} that only display the actual value of the model, not its name.
	 *  
	 * Should not change after construction of the {@link JView}.
	 * 
	 * @return		Whether view is self-naming
	 */
	public boolean selfNaming();
	
	/**
	 * This describes the format of the JView, for
	 * example it may be a small single line component,
	 * a medium sized component that spans several "lines",
	 * or a large component that users may wish to hide
	 *  
	 * Should not change after construction of the {@link JView}.
	 * 
	 * @return		The {@link Format} of the {@link JView}
	 */
	public Format format();
}
